﻿#nullable disable
using Furion.DependencyInjection;
using IMES.Entity;
using Mapster;
using SqlSugar;
using System.Diagnostics.CodeAnalysis;
using System.Text;

namespace IMES.BLL
{
    public class OrderRep : BaseRepository<Order>, ITransient
    {
        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="data"></param>
        public void ImportOrder(OrderImportData data)
        {
            try
            {
                Context.Ado.BeginTran();

                List<string> CpoList = data.Orders.GroupBy(x => x.CPO).Select(x => x.Key).ToList();
                List<Order> UpdateOrders = Context.Queryable<Order>().Where(x => SqlFunc.ContainsArray(CpoList, x.CPO)).ToList();
                List<string> updateCpos = UpdateOrders.Select(x => x.CPO).ToList();

                var orderStorageable = Context.Storageable(data.Orders)
                    .SplitError(x => string.IsNullOrWhiteSpace(x.Item.CPO), "CPO不能为空!")
                    .SplitError(x => string.IsNullOrWhiteSpace(x.Item.StyleNo), "款号不能为空!")
                    .SplitInsert(x => true)
                    .SplitUpdate(x => SqlFunc.ContainsArray(updateCpos, x.Item.CPO))
                    .ToStorage();

                //Console.WriteLine("Order 插入 {0} 更新{1} 错误数据{2} 不计算数据{3} 删除数据{4},总共{5}",
                //    orderStorageable.InsertList.Count,
                //    orderStorageable.UpdateList.Count,
                //    orderStorageable.ErrorList.Count,
                //    orderStorageable.IgnoreList.Count,
                //    orderStorageable.DeleteList.Count,
                //    orderStorageable.TotalList.Count
                //);

                StringBuilder errStr = new StringBuilder();
                foreach (var item in orderStorageable.ErrorList)
                {
                    errStr.Append(item.Item.CPO + " : " + item.StorageMessage);
                }
                if (errStr.Length > 0) throw new Exception(errStr.ToString());

                orderStorageable.AsInsertable.ExecuteCommand(); //执行插入
                orderStorageable.AsUpdateable.ExecuteCommand(); //执行更新 

                //删除记录
                Context.Deleteable<Orderdtl>(x => SqlFunc.ContainsArray(CpoList, x.CPO)).ExecuteCommand();

                var orderDtlStg = Context.Storageable(data.OrderDtls)
                  .SplitError(x => string.IsNullOrWhiteSpace(x.Item.ColorCode), "颜色不能为空!")
                  .SplitError(x => string.IsNullOrWhiteSpace(x.Item.Size), "尺码不能为空!")
                  .SplitError(x => string.IsNullOrWhiteSpace(x.Item.ABS_NO), "PO.ITEM不能为空!")
                  .SplitInsert(x => true)
                  .ToStorage();

                errStr = new StringBuilder();
                foreach (var item in orderDtlStg.ErrorList)
                {
                    errStr.Append($"CPO:{item.Item.CPO}/颜色:{item.Item.ColorCode}/PO.ITEM:{item.Item.ABS_NO}/尺码:{item.Item.Size}" + item.StorageMessage);
                }
                if (errStr.Length > 0) throw new Exception(errStr.ToString());

                // 订单详情
                orderDtlStg.AsInsertable.ExecuteCommand();

                // 导入历史记录 A.原记录标记为删除
                Context.Updateable<OrderImporthistory>()
                    .SetColumns(it => new OrderImporthistory { Usable = false,IsDeleted=true })
                    .Where((x => SqlFunc.ContainsArray(CpoList, x.CPO)))
                    .ExecuteCommand();

                //导入历史记录 B.插入新记录
                var historyStg = Context.Storageable(data.History)
                    .SplitError(x => string.IsNullOrWhiteSpace(x.Item.ColorCode), "颜色不能为空!")
                    .SplitError(x => string.IsNullOrWhiteSpace(x.Item.Size), "尺码不能为空!")
                    .SplitError(x => string.IsNullOrWhiteSpace(x.Item.ABS_NO), "PO.ITEM不能为空!")
                    .SplitInsert(x => true)
                    .ToStorage();
                historyStg.AsInsertable.ExecuteCommand();

                //尺码
                var customcodes = data.Orders.GroupBy(x => x.CustomerCode).Select(x => x.Key).ToList();
                var clothSizeList = Context.Queryable<BsClothsize>().Where(x => SqlFunc.ContainsArray(customcodes, x.CustomerCode)).ToList();
                var addSizeList = data.Clothsize;
                List<BsClothsize> maxSortIdList = null;
                if (clothSizeList != null && clothSizeList.Count > 0)
                {
                    addSizeList = data.Clothsize.Except(clothSizeList, new ClothSizeComparer()).ToList();
                    maxSortIdList = clothSizeList.GroupBy(x => x.CustomerCode).Select(x => new BsClothsize
                    { 
                        CustomerCode = x.Key,
                        SortID =x.Max(y=>y.SortID)
                    }).ToList();
                }
                else
                {
                    maxSortIdList = customcodes.GroupBy(x => x).Select(x => new BsClothsize
                    {
                        CustomerCode = x.Key,
                        SortID = 1
                    }).ToList();
                }
                FormatClothSizeSort(addSizeList, maxSortIdList);

                var clothSizeStag = Context.Storageable(addSizeList).SplitInsert(x => true).ToStorage();
                clothSizeStag.AsInsertable.ExecuteCommand();

                Context.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                Context.Ado.RollbackTran();
            }
        }

        private void FormatClothSizeSort(List<BsClothsize> customcodes, List<BsClothsize> sortIds)
        {
            List<BsClothsize> tempList = null;
            int tempMaxId = 1;
            sortIds.ForEach(x =>
            {
                tempList = customcodes.Where(y => y.CustomerCode == x.CustomerCode).Select(y=>y).ToList();
                tempMaxId = (x.SortID+1);
                foreach (var item in tempList)
                {
                    item.SortID = tempMaxId;
                    tempMaxId++;
                }
            });
        }

        /// <summary>
        /// 款式筛选
        /// </summary>
        /// <param name="filterTxt"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public List<OrderStyleOutput> StyleFilter(string filterTxt)
        {
            try
            {
                int totalNum = 0;
                List<OrderStyleOutput> styleList = Context.Queryable<Order>()
                .GroupBy(a => new {a.BUY,a.CustomerCode, a.StyleNo, a.StyleName})
                .WhereIF(!string.IsNullOrWhiteSpace(filterTxt),a=>a.StyleNo.Contains(filterTxt))
                .Select(a => new OrderStyleOutput
                {
                    BUY = a.BUY,
                    CustomerCode = a.CustomerCode,
                    StyleNo = a.StyleNo,
                    StyleName = a.StyleName,
                })
                .OrderBy(a => a.StyleNo)
                .ToPageList(1, 500, ref totalNum);
                return styleList;
            }
            catch (Exception ex)
            {
                throw new Exception($"款式筛选错误：{ex.Message}");
            }
        }

        /// <summary>
        /// 订单筛选
        /// </summary>
        /// <param name="style"></param>
        /// <returns></returns>
        public List<OrderOutput> StyleOrder(OrderStyleOutput style)
        {
            List<OrderOutput> orders = Context.Queryable<Order>()
                .Where((a) => a.CustomerCode == style.CustomerCode && a.StyleNo == style.StyleNo && a.BUY == style.BUY)
                .ToList().Adapt<List<OrderOutput>>();

            var cpoList = orders.GroupBy(a => a.CPO).Select(a => a.Key).ToList();
            List<OrderOutput> dtlList = Context.Queryable<Orderdtl>()
                .Where(a => SqlFunc.ContainsArray(cpoList, a.CPO))
                .GroupBy(a => new { a.CPO, a.ColorCode, a.ABS_NO, a.ShipDate, a.ChangeDate, a.ColorName })
                .Select(a => new OrderOutput()
                {
                    CPO = a.CPO,
                    ColorCode = a.ColorCode,
                    ABS_NO = a.ABS_NO,
                    ShipDate = a.ShipDate,
                    ChangeDate = a.ChangeDate,
                    ColorName = a.ColorName,
                    Qty = SqlFunc.AggregateSum(a.Qty),
                    CutQty = SqlFunc.AggregateSum(a.CutQty),
                })
                .ToList();

            List<OrderOutput> result = new List<OrderOutput>();
            foreach (var cpoitem in orders)
            {
                var items = dtlList.Where(a => a.CPO == cpoitem.CPO).ToList();
                if (items != null && items.Count > 0)
                {
                    foreach (var item in items)
                    {
                        result.Add(cpoitem.Adapt<OrderOutput>());
                        result[result.Count - 1].ColorCode = item.ColorCode;
                        result[result.Count - 1].ABS_NO = item.ABS_NO;
                        result[result.Count - 1].ShipDate = item.ShipDate;
                        result[result.Count - 1].ChangeDate = item.ChangeDate;
                        result[result.Count - 1].ColorName = item.ColorName;
                        result[result.Count - 1].Qty = item.Qty;
                        result[result.Count - 1].CutQty = item.CutQty;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 获取订单详情列表
        /// </summary>
        /// <param name="cpo"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public List<OrderDtlOutput> GetDtlList(string cpo)
        {
            var list = Context.Queryable<Orderdtl>()
                .InnerJoin<Order>((a, b) => a.CPO == b.CPO)
                .InnerJoin<BsClothsize>((a, b, c) => b.CustomerCode == c.CustomerCode && a.Size == c.Size)
                .Where((a, b, c) => a.CPO == cpo)
                .OrderBy((a, b, c) => new { a.ColorCode, c.SortID })
                .Select((a, b, c) => new OrderDtlOutput
                {
                    ABS_NO = a.ABS_NO,
                    ChangeDate = a.ChangeDate,
                    ColorCode = a.ColorCode,
                    Qty = a.Qty,
                    CutQty = a.CutQty,
                    ColorName = a.ColorName,
                    CPO = a.CPO,
                    INT_ColorCode = a.INT_ColorCode,
                    JCBL = a.JCBL,
                    ShipDate = a.ShipDate,
                    Size = a.Size,
                    Id = a.Id,
                })
                .ToList();
            return list;
        }

        /// <summary>
        /// 获取订单导入历史列表
        /// </summary>
        /// <param name="cpo"></param>
        /// <returns></returns>
        public List<OrderImporthistory> GetHistory(string cpo)
        {
            var list = Context.Queryable<OrderImporthistory>() 
                .Where((a) => a.CPO == cpo )
                .OrderBy((a) => new { a.CreateTime,a.Id },OrderByType.Desc)
                .ToList();
            return list;
        }
    }


    class ClothSizeComparer : IEqualityComparer<BsClothsize>
    {
        public bool Equals(BsClothsize x, BsClothsize y) => (x.CustomerCode == y.CustomerCode && x.Size == y.Size);
        public int GetHashCode([DisallowNull] BsClothsize obj) => obj == null ? 0 : obj.ToString().GetHashCode();
    }
}
